package com.zglc.ms.shop.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zglc.ms.base.constants.ResponseCodeHelper;
import com.zglc.ms.base.service.BizServiceException;
import com.zglc.ms.base.util.DateUtil;
import com.zglc.ms.shop.controller.log.RequestLog;
import com.zglc.ms.shop.dao.PointUserDao;
import com.zglc.ms.shop.dao.TransDao.TransModel;
import com.zglc.ms.shop.filter.JwtHelper;
import com.zglc.ms.shop.model.ShopProduct;
import com.zglc.ms.shop.model.UserAddress;
import com.zglc.ms.shop.service.*;
import com.zglc.ms.shop.util.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Random;

import static com.zglc.ms.shop.util.CommonUtils.*;

@Controller
@RequestMapping("/front/trans")
public class TransController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private ShopProductService shopProductService;

    @Autowired
    private AddressService addressService;

    @Autowired
    private TransService transService;

    @Autowired
    private CacheManagerUtil cacheManagerUtil;

    @Autowired
    private PointUserDao pointUserDao;

    @Autowired
    private PointService pointService;

    @RequestMapping("/check")
    @ResponseBody
    @RequestLog
    public Map<String, Object> check(HttpServletRequest request, @RequestParam int shopProductId,
            @RequestParam int cnt) {
        Map<String, Object> map = CommonUtils.successResponse();
        Integer userId = JwtHelper.getUserId(request);

        ShopProduct shopProduct = shopProductService.getProductDetailById(shopProductId);
        map = preCheck(map, userId, shopProduct, cnt, true);
        if (!isPreCheckSuccess(map)) {
            return map;
        }

        return map;
    }

    @RequestMapping("/buy")
    @ResponseBody
    @RequestLog
    public Map<String, Object> buy(HttpServletRequest request, @RequestParam int shopProductId, @RequestParam int cnt,
            @RequestParam int platfrom, @RequestParam String payChannel, @RequestParam String remark,
            @RequestParam(required = false) Integer addressId, @RequestParam(required = false) Integer transId) {
        Map<String, Object> map = CommonUtils.successResponse();
        Integer userId = JwtHelper.getUserId(request);
        if (userId == null) {
            return CommonUtils.userNotExistResponse();
        }

        logger.info("shopProductId = " + shopProductId + " cnt = " + cnt + " platfrom = " + platfrom + " payChannel "
                + payChannel + " userId " + userId + " remark " + remark + " addressId " + addressId);
        ShopProduct shopProduct;
        int transPoint = 0;
        long no;
        int id = 0;
        boolean isNewOrder = true;
        int priceType;
        String priceDetail, payDetail;;
        if (transId != null && transId > 0) {
            TransModel transModel = transService.get(transId);
            if (transModel == null) {
                map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
                map.put(RETURN_MSG, "订单无效, 请重新购买");
                return map;
            }

            if (transModel.getState() == 2) {
                map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
                map.put(RETURN_MSG, "订单已支付");
                return map;
            }

            if (transService.isOrderCancel(transModel)) {
                map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
                map.put(RETURN_MSG, "订单已超时, 请重新发起");
                return map;
            }

            shopProduct = shopProductService.getProductDetailById(transModel.getShopProductId());
            payDetail = transModel.getPayDetail();
            if (StringUtils.isEmpty(payDetail)) {
                map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
                map.put(RETURN_MSG, "订单无效, 请重新购买");
                return map;
            }

            String[] payPoints = payDetail.split(CommonUtils.SPLIT);
            if (payPoints.length%2 != 0) {
                map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
                map.put(RETURN_MSG, "订单无效, 请重新购买");
                return map;
            }

            try {
            	priceType = Integer.parseInt(payPoints[0]);
                transPoint = Integer.parseInt(payPoints[1]);
            } catch (Exception e) {
                map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
                map.put(RETURN_MSG, "订单无效, 请重新购买");
                return map;
            }

            priceDetail = transModel.getPriceDetail();
            addressId = transModel.getSendAddressId();
            no = transModel.getOrderNo();
            id = transModel.getId();
            cnt = transModel.getGoodCnt();
            isNewOrder = false;
            if (!cacheManagerUtil.isExist(CacheManagerUtil.CACHE_BUYING + shopProductId + no)) {
                isNewOrder = true;
            }

        } else {
            if (cnt <= 0) {
                return map;
            }

            shopProduct = shopProductService.getProductDetailById(shopProductId);
            if (shopProduct == null) {
                map.put(RETURN_CODE, ResponseCodeHelper.GOODS_NOT_ON_SELLING);
                map.put(RETURN_MSG, "所购买的商品已下架");
                return map;
            }

            priceType = shopProduct.getPriceType();
            transPoint = cnt * (int)shopProduct.getPricePoint();
            priceDetail = shopProduct.getPriceType() + CommonUtils.SPLIT + shopProduct.getPricePoint();
            payDetail = priceType + CommonUtils.SPLIT + transPoint;
            no = System.currentTimeMillis() + new Random().nextInt(1000000);
            // 购买检查只检查未下单操作，不检查待支付操作
        }

        logger.info(shopProduct.toString() + " transPoint = " + transPoint);
        if (transPoint <= 0) {
            map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
            map.put(RETURN_MSG, "请稍后再试");
            return map;
        }

        map = preCheck(map, userId, shopProduct, cnt, isNewOrder);
        if (!isPreCheckSuccess(map)) {
            return map;
        }

        boolean isSend = (shopProduct.getIsSend() == 1);
        String address = "";
        String phone = "";
        String contact = "";
        if (isSend) {
            if (addressId == null || addressId <= 0) {
                map.put(RETURN_CODE, ResponseCodeHelper.GOODS_HAS_NOT_RECEIVE_ADDRESS);
                map.put(RETURN_MSG, "商品需发货, 请填写地址");
                return map;
            }

            UserAddress userAddress = addressService.getAddressById(addressId);
            if (userAddress == null) {
                map.put(RETURN_CODE, ResponseCodeHelper.GOODS_HAS_NOT_RECEIVE_ADDRESS);
                map.put(RETURN_MSG, "商品需发货, 请填写有效地址");
                return map;
            }

            address = userAddress.getRemark();
            phone = userAddress.getPhone();
            contact = userAddress.getContact();
        }

        if (isNewOrder) {
            // 添加正在支付中的金额
            cacheManagerUtil.jSet(CacheManagerUtil.CACHE_BUYING + shopProductId + no, String.valueOf(cnt),
                    CacheManagerUtil.PAY_VALID_TIME);
        }
        
        if (transId == null || transId <= 0) {
            id = transService.save(userId, no, shopProductId, priceDetail, cnt, payDetail, payChannel, platfrom, isSend,
                    remark, addressId, address, phone, contact);
        }

        JSONObject jo = new JSONObject();
        jo.put("transId", id);
        map.put(RETURN_DATA, jo);

        //TODO 扣除积分, 交易完成
        try {
            transService.successProcess(userId, shopProduct, cnt, id, false, "", priceType,
                    transPoint);
        } catch (BizServiceException e) {
            e.printStackTrace();
            map.put(RETURN_CODE, e.getCode());
            map.put(RETURN_MSG, e.getMessage());
        }

        cacheManagerUtil.jDel(CacheManagerUtil.CACHE_BUYING + shopProductId + no);
        return map;
    }

    @RequestMapping("/getInfo")
    @ResponseBody
    @RequestLog
    public Map<String, Object> getInfo(HttpServletRequest request, @RequestParam int transId) {
        Map<String, Object> map = CommonUtils.successResponse();
        if (transId <= 0) {
            map.put(RETURN_CODE, ResponseCodeHelper.CALLER_PARAMS_INVALID_ERROR);
            map.put(RETURN_MSG, "参数错误");
            return map;
        }

        Integer userId = JwtHelper.getUserId(request);
        if (userId == null) {
            return CommonUtils.userNotExistResponse();
        }

        TransModel transModel = transService.get(transId);
        if (transModel == null || transModel.getUserId() != userId) {
            map.put(RETURN_CODE, ResponseCodeHelper.CALLER_PARAMS_INVALID_ERROR);
            map.put(RETURN_MSG, "订单不存在");
            return map;
        }

        ShopProduct prodInfo = shopProductService.getProductShowTransById(transModel.getShopProductId());
        JSONObject jo = new JSONObject();
        setPoint(transModel.getPayDetail(), map, jo);
        if (!isPreCheckSuccess(map)) {
            return map;
        }
        String ruleName = pointService.getRuleMap().get(prodInfo.getPriceType());
        jo.put("shopProductId", prodInfo.getId());
        jo.put("shopProductName", prodInfo.getName());
        jo.put("shopProductImgUrl", prodInfo.getImgSmallUrl());
        jo.put("cnt", transModel.getGoodCnt());

        jo.put("date", DateUtil.datetime2String(transModel.getCreatedAt()));
        jo.put("state", transModel.getState());
        jo.put("orderNo", transModel.getOrderNo());
        jo.put("remark", transModel.getRemark());
        jo.put("isNeedSend", transModel.isNeedSend());
        jo.put("isSend", transModel.isSend());
        jo.put("priceName",ruleName);
        if (!StringUtils.isEmpty(transModel.getAddress())) {
            jo.put("isHasAddress", true);
            jo.put("address", transModel.getAddress());
            jo.put("phone", transModel.getPhone());
            jo.put("contact", transModel.getContact());
        } else {
            jo.put("isHasAddress", false);
            jo.put("address", "");
            jo.put("phone", "");
            jo.put("contact", "");
        }

        map.put(RETURN_DATA, jo);
        return map;
    }

    @RequestMapping("/getHistory")
    @ResponseBody
    @RequestLog
    public Map<String, Object> getHistory(HttpServletRequest request, @RequestParam int page,
            @RequestParam int pageNum) {
        Map<String, Object> map = CommonUtils.successResponse();
        Integer userId = JwtHelper.getUserId(request);
        if (userId == null) {
            return CommonUtils.userNotExistResponse();
        }

        List<TransModel> list = transService.getByUserId(userId, page, pageNum);
        Integer cnt = transService.getByUserIdCnt(userId);
        if (CollectionUtils.isEmpty(list)) {
            map.put(RETURN_DATA, new JSONArray());
            map.put("cnt", 0);
            return map;
        }

        Map<Integer, String> ruleMap = pointService.getRuleMap();

        JSONArray ja = new JSONArray();
        for (TransModel transModel : list) {
            ShopProduct prodInfo = shopProductService.getProductShowTransById(transModel.getShopProductId());
            JSONObject jo = new JSONObject();
            
            if (StringUtils.isEmpty(transModel.getPayDetail())) {
                continue;
            }

            String[] payPoints = transModel.getPayDetail().split(CommonUtils.SPLIT);
            if (payPoints.length%2 != 0) {
            	continue;
            }

            try {
                jo.put("priceType", Integer.parseInt(payPoints[0]));
                jo.put("pricePoint", Integer.parseInt(payPoints[1]));
            } catch (Exception e) {
            	continue;
            }
            jo.put("priceName",ruleMap.get(prodInfo.getPriceType()));
            jo.put("transId", transModel.getId());
            jo.put("date", DateUtil.date2String(transModel.getCreatedAt()));
            jo.put("state", transModel.getState());
            jo.put("shopProductId", transModel.getShopProductId());
            jo.put("shopProductName", prodInfo.getName());
            jo.put("shopProductImgUrl", prodInfo.getImgSmallUrl());
            jo.put("imgSmallUrl", prodInfo.getImgSmallUrl());

            jo.put("remark", transModel.getRemark());
            jo.put("goodCnt", transModel.getGoodCnt());
            jo.put("isSend", transModel.isSend());
            
            if (!StringUtils.isEmpty(transModel.getAddress())) {
                jo.put("isHasAddress", true);
                jo.put("address", transModel.getAddress());
                jo.put("phone", transModel.getPhone());
                jo.put("contact", transModel.getContact());
            } else {
                jo.put("isHasAddress", false);
                jo.put("address", "");
                jo.put("phone", "");
                jo.put("contact", "");
            }
            ja.add(jo);
        }

        map.put(RETURN_DATA, ja);
        map.put("cnt", cnt);
        return map;
    }

    // transModel.getPayDetail();
    private Map<String, Object> setPoint(String payDetail, Map<String, Object> map, JSONObject jo) {
        if (StringUtils.isEmpty(payDetail)) {
            map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
            map.put(RETURN_MSG, "订单无效, 请重新购买");
            return map;
        }

        String[] payPoints = payDetail.split(CommonUtils.SPLIT);
        if (payPoints.length%2 != 0) {
            map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
            map.put(RETURN_MSG, "订单无效, 请重新购买");
            return map;
        }

        try {
            jo.put("priceType", Integer.parseInt(payPoints[0]));
            jo.put("pricePoint", Integer.parseInt(payPoints[1]));
        } catch (Exception e) {
            map.put(RETURN_CODE, ResponseCodeHelper.COMMON_SYSTEM_EXCEPTION);
            map.put(RETURN_MSG, "订单无效, 请重新购买");
            return map;
        }

        return map;
    }

    private boolean isPreCheckSuccess(Map<String, Object> map) {
        Object codeObj = map.get(RETURN_CODE);
        try {
            return ResponseCodeHelper.SUCCESS == Integer.parseInt(codeObj.toString());
        } catch (Exception e) {
            logger.info(codeObj.toString());
            return false;
        }
    }

    private Map<String, Object> preCheck(Map<String, Object> map, int userId, ShopProduct shopProduct, int cnt,
            boolean isNewOrder) {
        if (shopProduct == null) {
            map.put(RETURN_CODE, ResponseCodeHelper.NO_PRODUCTS_BY_ID);
            map.put(RETURN_MSG, "所购买的商品不存在");
            return map;
        }

        if (shopProduct.getIsUp() == 0) {
            map.put(RETURN_CODE, ResponseCodeHelper.GOODS_NOT_ON_SELLING);
            map.put(RETURN_MSG, "所购买的商品已下架");
            return map;
        }

        if (shopProduct.getInventoryNum() - shopProduct.getRealSaledNum() <= 0) {
            map.put(RETURN_CODE, ResponseCodeHelper.GOODS_SELL_NOT_REMAIN);
            map.put(RETURN_MSG, "所购买的商品已售罄");
            return map;
        }

        // 检查正在支付中的库存
        long allBuyingCnt = cacheManagerUtil.getAllBuyingCnt(CacheManagerUtil.CACHE_BUYING + shopProduct.getId());
        long totalBuyCnt = allBuyingCnt + shopProduct.getRealSaledNum();
        if (isNewOrder) {
            totalBuyCnt += cnt;
        }

        logger.debug("allBuyingCnt = " + allBuyingCnt + " cnt = " + cnt + " shopProduct.getSaledNum() = "
                + shopProduct.getRealSaledNum() + " shopProduct.getInventoryNum() = " + shopProduct.getInventoryNum()
                + " totalBuyCnt = " + totalBuyCnt + " isNewOrder = " + isNewOrder);

        if (totalBuyCnt > shopProduct.getInventoryNum()) {
            map.put(RETURN_CODE, ResponseCodeHelper.GOODS_NOT_ON_SELLING);
            map.put(RETURN_MSG, "所购买的商品已售罄");
            return map;
        }
        map = preCheckPoint(map, userId, shopProduct, cnt);
        return map;
    }

    private Map<String, Object> preCheckPoint(Map<String, Object> map, int userId, ShopProduct shopProduct, int cnt) {
        int cnt1 = pointUserDao.getPointUserByUserId(userId, shopProduct.getPriceType(),
                shopProduct.getPricePoint() * cnt);
        if (cnt1 <= 0) {
            map.put(RETURN_CODE, ResponseCodeHelper.NOT_BUY_USER_POINTS_LOWER);
            map.put(RETURN_MSG, "用户积分不足, 商品无法购买");
            return map;
        } else {
            map.put(RETURN_CODE, 0);
            map.put(RETURN_MSG, "可以购买");
            return map;
        }

    }

}